package com.siqi.hr.common.mongo;

import com.alibaba.fastjson.JSONObject;
import com.mongodb.BasicDBObject;
import com.mongodb.client.AggregateIterable;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.model.FindOneAndUpdateOptions;
import com.siqi.hr.common.Constants;
import org.bson.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * Mongo操作API通用工具类(主要是增删该查，有其它业务可以添加)
 * @author    xiaogq
 */
public class MongoAPI {
    static Logger log = LoggerFactory.getLogger(MongoAPI.class);

    /**
     * 插入数据(xiaogq)
     * @param dbName			     库名(redis数据库名)
     * @param collection			具体某个库的集合名/表名
     * @param obj					要添加的数据
     */
    public static void insert(String dbName,String collection,JSONObject obj) {
        try {
            // 连接集合(类似于RDBMS)中的表,若没有,则新建
            MongoCollection<Document> coll = MongoDBManager.getInstance().getDB(dbName).getCollection(collection);
            //获取序列号从1开始
            //String tempIndex = getNextId(coll,"id");
            //obj.put("id", Integer.parseInt(tempIndex));
            //添加索引
            MongoAPI.createIndex(coll);
            coll.insertOne(Document.parse(obj.toString()));
        } catch (Exception e) {
            log.warn("Error",e);
        }
    }

    /**
     * 批量添加数据(xiaogq)
     * @param dbName			     库名(redis数据库名)
     * @param collection			具体某个库的集合名/表名
     * @param listObj				要批量添加的数据
     */
    public static void batchInsert(String dbName, String collection, List<Document> listObj) {
        try {
            // 连接集合(类似于RDBMS)中的表,若没有,则新建
            MongoCollection<Document> coll = MongoDBManager.getInstance().getDB(dbName).getCollection(collection);
            coll.insertMany(listObj);
        } catch (Exception e) {
            log.warn("Error",e);
        }
    }

    /**
     * 生成序列(xiaogq)
     * @param coll			    建表对象
     * @param seq_name		值
     * @return
     */
    private static String getNextId(MongoCollection<Document> coll,String seq_name) {
        // the name of the field which holds the sequence
        String sequence_field = "seq";
        // this object represents your "query", its analogous to a WHERE clause in SQL
        BasicDBObject query = new BasicDBObject();
        // where _id = the input sequence name
        query.put("_id", seq_name);
        // this object represents the "update" or the SET blah=blah in SQL
        BasicDBObject change = new BasicDBObject(sequence_field, 1);
        // the $inc here is a mongodb command for increment
        BasicDBObject update = new BasicDBObject("$inc", change);
        // DBObject res = seq.findAndModify(query, new BasicDBObject(), new BasicDBObject(), false, update, true, true);
        FindOneAndUpdateOptions options =  new FindOneAndUpdateOptions();
        options.upsert(true);
        Document doc = coll.findOneAndUpdate(query, update, options);
        if(doc != null){
            return doc.get(sequence_field).toString();
        }else{
            return "";
        }
    }

    /**
     * 查看所有(xiaogq)
     * @param dbName		    库名
     * @param collection		表名/集合名
     * @return
     */
    public static MongoCursor<Document> query(String dbName,String collection) {
        //执行前查询前时间(毫秒)
        long start = System.currentTimeMillis();
        MongoCursor<Document> cursor = null;
        try {
            // 连接集合(类似于RDBMS)中的表,若没有,则新建
            MongoCollection<Document> coll = MongoDBManager.getInstance().getDB(dbName).getCollection(collection);
            //返回10000条数据
            FindIterable<Document> iter = coll.find().batchSize(Constants.BATCHSIZE);
            cursor = iter.iterator();
            //执行后查询前时间(毫秒)
            long end = System.currentTimeMillis();
            log.debug("MongodbDataAPI查询用时 -query方法："+(end -start)+"ms"+"查询数据query>>>>>"+cursor.hasNext());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cursor;
    }

    /**
     * 根据条件查询带排序(xiaogq)
     * @param dbName					库名
     * @param collection				表名/集合名
     * @param queryObject			查询条件
     * @param sort					排序条件
     * @return
     */
    public static MongoCursor<Document> queryWhere(String dbName,String collection, BasicDBObject queryObject, BasicDBObject sort) {
        long start = System.currentTimeMillis();
        MongoCursor<Document> cursor = null;
        try {
            // 连接集合(类似于RDBMS)中的表,若没有,则新建
            MongoCollection<Document> coll = MongoDBManager.getInstance().getDB(dbName).getCollection(collection);

            FindIterable<Document> iter = coll.find(queryObject).batchSize(Constants.BATCHSIZE).sort(sort);
            cursor = iter.iterator();
            long end = System.currentTimeMillis();
            log.debug("MongodbDataAPI查询用时  -queryWhere 2参方法："+(end -start)+"ms"+"查询数据query>>>>>"+cursor.hasNext());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cursor;
    }

    /***
     * 根据条件查询带分页排序(xiaogq)
     * @param dbName				    库名
     * @param collection				表名
     * @param queryObject		        条件
     * @param sort				        排序
     * @param skip				        跳过多少条
     * @param limit				    取多少条
     * @return
     */
    public static MongoCursor<Document> queryWhere(String dbName,String collection,BasicDBObject queryObject,BasicDBObject sort, int skip, int limit) {
        long start = System.currentTimeMillis();
        MongoCursor<Document> cursor = null;
        try {
            // 连接集合(类似于RDBMS)中的表,若没有,则新建
            MongoCollection<Document> coll = MongoDBManager.getInstance().getDB(dbName).getCollection(collection);
            log.debug("查询条件："+queryObject.toString());
            FindIterable<Document> iter = coll.find(queryObject).batchSize(Constants.BATCHSIZE).sort(sort).limit(limit).skip(skip);
            cursor = iter.iterator();
            long end = System.currentTimeMillis();
            log.debug("MongodbDataAPI查询用时  -queryWhere 5参方法："+(end -start)+"ms"+"查询数据query>>>>>"+cursor.hasNext());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cursor;
    }

    /**
     * 根据条件查询带排序查询哪些列(xiaogq)
     * @param dbName				    库名
     * @param collection				表名/集合名
     * @param queryObject		        查询条件
     * @param projection		        显示哪列
     * @param sort				        排序
     * @return
     */

    public static MongoCursor<Document> queryWhere(String dbName,String collection,BasicDBObject queryObject,BasicDBObject projection,BasicDBObject sort) {
        long start = System.currentTimeMillis();
        MongoCursor<Document> cursor = null;
        try {
            // 连接集合(类似于RDBMS)中的表,若没有,则新建
            MongoCollection<Document> coll = MongoDBManager.getInstance().getDB(dbName).getCollection(collection);
            FindIterable<Document> iter = null;
            if(queryObject !=null){
                iter = coll.find(queryObject).batchSize(Constants.BATCHSIZE).projection(projection).sort(sort);
            }else{
                iter = coll.find().batchSize(Constants.BATCHSIZE).projection(projection).sort(sort);
            }
            cursor = iter.iterator();
            long end = System.currentTimeMillis();
            log.debug("MongodbDataAPI查询用时  -queryWhere 4参方法："+(end -start)+"ms"+"查询数据query>>>>>"+cursor.hasNext());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cursor;
    }

    /**
     * 查询最大一条数据(xiaogq)
     * @param dbName			    库名
     * @param collection			表名/集合名
     * @param sort			        排序
     * @return
     */
    public static String queryMax(String dbName,String collection,BasicDBObject sort) {
        long start = System.currentTimeMillis();
        String jsonStr = "";
        MongoCursor<Document> cursor = null;
        try {
            // 连接集合(类似于RDBMS)中的表,若没有,则新建
            MongoCollection<Document> coll =  MongoDBManager.getInstance().getDB(dbName).getCollection(collection);
            FindIterable<Document> iter = coll.find().sort(sort).limit(1);
            cursor = iter.iterator();
            if(cursor.hasNext()){
                jsonStr = cursor.next().toJson();
            }
            long end = System.currentTimeMillis();
            log.debug("MongodbDataAPI查询用时 -max（2参）："+(end - start)+"ms --------"+"查询数据queryMax >>>>>"+cursor.hasNext());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return jsonStr;
    }

    /**
     * 根据查询条件查询最大一条数据(xiaogq)
     * @param dbName				    库名
     * @param collection				表名/集合名
     * @param queryObject		        查询条件
     * @param sort				        排序
     * @return
     */
    public static String queryMax(String dbName,String collection, BasicDBObject queryObject,BasicDBObject sort) {
        long start = System.currentTimeMillis();
        String jsonStr = "";
        MongoCursor<Document> cursor = null;
        try {
            // 连接集合(类似于RDBMS)中的表,若没有,则新建
            MongoCollection<Document> coll =  MongoDBManager.getInstance().getDB(dbName).getCollection(collection);
            FindIterable<Document> iter = null;
            if(queryObject !=null){
                iter = coll.find(queryObject).sort(sort).limit(1);
            }else{
                iter = coll.find().sort(sort).limit(1);
            }
            cursor = iter.iterator();
            if(cursor.hasNext()){
                jsonStr = cursor.next().toJson();
            }
            long end = System.currentTimeMillis();
            log.debug("MongodbDataAPI查询用时-max（3参）："+(end - start)+"ms --------"+"查询数据queryMax >>>>>"+cursor.hasNext());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return jsonStr;
    }

    /**
     * 查询最大一条数据 3参
     * @param dbName				库名
     * @param collection		    表名/集合名
     * @param queryObject		    查询条件
     * @param projection		    查询结果返回哪些列
     * @param sort				    排序
     * @return
     */
    public static String queryMax(String dbName,String collection, BasicDBObject queryObject,BasicDBObject projection, BasicDBObject sort) {
        long start = System.currentTimeMillis();
        String jsonStr = "";
        MongoCursor<Document> cursor = null;
        try {
            // 连接集合(类似于RDBMS)中的表,若没有,则新建
            MongoCollection<Document> coll =  MongoDBManager.getInstance().getDB(dbName).getCollection(collection);
            FindIterable<Document> iter = null;
            if(queryObject !=null){
                iter = coll.find(queryObject).projection(projection).sort(sort).limit(1);
            }else{
                iter = coll.find().projection(projection).sort(sort).limit(1);
            }
            cursor = iter.iterator();
            if(cursor.hasNext()){
                jsonStr = cursor.next().toJson();
            }
            long end = System.currentTimeMillis();
            log.debug("MongodbDataAPI查询用时-max（3参）："+(end - start)+"ms --------"+"查询数据queryMax >>>>>"+cursor.hasNext());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return jsonStr;
    }
    /**
     * 根据条件查询总共有多少条
     * @param dbName				库名
     * @param collection			表名/集合名
     * @param queryObject		    查询条件
     * @return
     */
    public static long count(String dbName,String collection,BasicDBObject queryObject) {
        long start = System.currentTimeMillis();
        long count = 0l;
        try {
            // 连接集合(类似于RDBMS)中的表,若没有,则新建
            MongoCollection<Document> coll = MongoDBManager.getInstance().getDB(dbName).getCollection(collection);
            if(queryObject !=null){
                count = coll.count(queryObject);
            }else{
                count = coll.count();
            }
            long end = System.currentTimeMillis();
            log.debug("MongodbDataAPI查询用时-count："+(end - start)+"ms --------"+"查询数据count>>>>>"+count);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return count;
    }

    /**
     * 查询指定数据库中某个集合中所有的记录数(xiaogq)
     * @param dbName				库名
     * @param collection			表名/集合名
     * @return
     */
    public static long count(String dbName,String collection) {
        return count(dbName,collection, null);
    }

    /**
     * 分组查询(xiaogq)
     * @param dbName				    库名
     * @param collection				表名/集合名
     * @param pipeline			    条件（并且关系）
     * @return
     */
    public static MongoCursor<Document> aggregate(String dbName,String collection, List<BasicDBObject> pipeline) {
        MongoCursor<Document> cursor = null;
        try {
            // 连接集合(类似于RDBMS)中的表,若没有,则新建
            MongoCollection<Document> coll = MongoDBManager.getInstance().getDB(dbName).getCollection(collection);
            AggregateIterable<Document> iter = coll.aggregate(pipeline).batchSize(Constants.BATCHSIZE);
            cursor = iter.iterator();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cursor;
    }

    /**
     * 删除指定数据(xiaogq)
     * @param dbName		    库名
     * @param collection		表名/集合名
     * @param flag		删除标识(1:删除表  2:删除一条数据只能根据id删除,3:删除多条数据)
     */
    public static void delete(String dbName,String collection,String flag,BasicDBObject queryObject) {
        try {
            // 连接集合(类似于RDBMS)中的表,若没有,则新建
            MongoCollection<Document> coll = MongoDBManager.getInstance().getDB(dbName).getCollection(collection);
            if("1".equals(flag)){
                coll.drop();
            }else if ("2".equals(flag)){
                coll.deleteOne(queryObject);
            }else if ("3".equals(flag)){
                coll.deleteMany(queryObject);
            }
        } catch (Exception e) {
            log.error("ERROR",e);
        }
    }

    /**
     * 更新数据(xiaogq)
     * @param dbName            库名
     * @param collection       表名/集合名
     * @param queryObject      满足修改数据的查询条件
     * @param newDocument      要修改的文档内容
     * @param flag              修改标识(1:修改一条数据只能根据id删除,2:修改多条数据，修改符合条件的数据)
     */
    public static void update(String dbName,String collection,BasicDBObject queryObject,BasicDBObject newDocument,String flag) {
        try {
            // 查找_id=556d7121d49c6f19e0c76c8e的文档(行)
            //BasicDBObject searchQuery = new BasicDBObject().append("_id",new ObjectId("556d7121d49c6f19e0c76c8e"));
            //System.out.println(searchQuery);
            //BasicDBObject newDocument = new BasicDBObject();
            // 将其中的Key为cust_id的值改为ABC123
            //newDocument.append("$set",new BasicDBObject().append("cust_id", "ABC123"));
            MongoCollection<Document> coll = MongoDBManager.getInstance().getDB(dbName).getCollection(collection);
            if ("1".equals(flag)){
                coll.updateOne(queryObject, newDocument);
            }else{
                coll.updateMany(queryObject,newDocument);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建索引(xiaogq)
     * @param coll  表
     */
    private static void createIndex(MongoCollection<Document> coll) {
        coll.createIndex(new BasicDBObject("id", 1));
    }

    /**
     * 删除索引方法(xiaogq)
     * @param dbName            库名
     * @param collection       表名/集合名
     * @param flag               删除索引状态(1:删除部分索引，2：删除集合中所有索引)
     */
    public static void deleteIndex(String dbName,String collection,String flag) {
        try {
            // 连接集合(类似于RDBMS)中的表,若没有,则新建
            MongoCollection<Document> coll = MongoDBManager.getInstance().getDB(dbName).getCollection(collection);
            if("1".equals(flag)){
                coll.dropIndex(new BasicDBObject("id", 1));
            }else{
                coll.dropIndexes();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}


